﻿'Copyright (c) 2009 Grailtek

'Permission is hereby granted, free of charge, to any person
'obtaining a copy of this software and associated documentation
'files (the "Software"), to deal in the Software without
'restriction, including without limitation the rights to use,
'copy, modify, merge, publish, distribute, sublicense, and/or sell
'copies of the Software, and to permit persons to whom the
'Software is furnished to do so, subject to the following
'conditions:

'The above copyright notice and this permission notice shall be
'included in all copies or substantial portions of the Software.

'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
'EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
'OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
'NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
'HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
'WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
'FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
'OTHER DEALINGS IN THE SOFTWARE.

Imports System.Reflection
Imports System.Aspect

Namespace Aspect

    '<DebuggerStepThrough()> _
    <CLSCompliant(True)> _
    Public Class DelegateInfo
        Public Sub New(ByVal iDelegateType As Type)
            _DeclaringDelegate = iDelegateType
            Dim atrs() As Object = _DeclaringDelegate.GetCustomAttributes(True)
            _Aspects = atrs.OfType(Of IAspect).ToArray
            _Actions = atrs.OfType(Of IAspectAction).ToArray
            _Functions = atrs.OfType(Of IAspectFunction).ToArray
            _MethodInfo = _DeclaringDelegate.GetMethod("Invoke")
            _InputMappings = InputMapping.GetMappings(_MethodInfo)
            _ParamCount = _InputMappings.GetUpperBound(0)
            _ReturnTypeIsArray = _MethodInfo.ReturnType.IsArray
            _ReturnType = If(_ReturnTypeIsArray, _MethodInfo.ReturnType.GetElementType, _MethodInfo.ReturnType)
            _ReturnTypeIsConstructable = _ReturnType.HasPublicParameterlessConstructor
            _OutputMappings = OutputMapping.GetMappings(_ReturnType)

            Dim p As PrimaryTypeAttribute = _ReturnType.GetCustomAttributes(True).OfType(Of PrimaryTypeAttribute).FirstOrDefault
            If p Is Nothing Then
                _DeclaredPrimaryInterface = _ReturnType
            Else
                _DeclaredPrimaryInterface = p.PrimaryType
            End If

            For Each aspect As IAspect In Aspects
                aspect.DelegateInfo = Me
            Next

        End Sub
        Private ReadOnly _Aspects() As IAspect
        Public ReadOnly Property Aspects() As IAspect()
            Get
                Return _Aspects
            End Get
        End Property
        Private ReadOnly _Actions() As IAspectAction
        Friend ReadOnly Property Actions() As IAspectAction()
            Get
                Return _Actions
            End Get
        End Property
        Private ReadOnly _Functions() As IAspectFunction
        Friend ReadOnly Property Functions() As IAspectFunction()
            Get
                Return _Functions
            End Get
        End Property


        Private ReadOnly _InputMappings() As InputMapping
        Public ReadOnly Property InputMappings() As InputMapping()
            Get
                Return _InputMappings
            End Get
        End Property

        Private ReadOnly _ParamCount As Integer

        Private ReadOnly _DeclaringDelegate As Type
        Public ReadOnly Property DeclaringDelegate() As Type
            Get
                Return _DeclaringDelegate
            End Get
        End Property
        Private ReadOnly _ReturnType As Type
        Public ReadOnly Property ReturnType() As Type
            Get
                Return _ReturnType
            End Get
        End Property

        Private ReadOnly _ReturnTypeIsConstructable As Boolean
        Public ReadOnly Property ReturnTypeIsConstructable() As Boolean
            Get
                Return _ReturnTypeIsConstructable
            End Get
        End Property
        Private ReadOnly _ReturnTypeIsArray As Boolean
        Public ReadOnly Property ReturnTypeIsArray() As Boolean
            Get
                Return _ReturnTypeIsArray
            End Get
        End Property
        Private ReadOnly _MethodInfo As MethodInfo
        Public ReadOnly Property MethodInfo() As MethodInfo
            Get
                Return _MethodInfo
            End Get
        End Property
        Private ReadOnly _OutputMappings() As OutputMapping
        <CLSCompliant(True)> _
        Public ReadOnly Property OutputMappings() As OutputMapping()
            Get
                Return _OutputMappings
            End Get
        End Property

        Private _DeclaredPrimaryInterface As Type
        Public ReadOnly Property DeclaredPrimaryInterface() As Type
            Get
                Return _DeclaredPrimaryInterface
            End Get
        End Property

        Public Function GetEmptyArgs() As Argument()
            Dim ret(_ParamCount) As Argument
            For i As Integer = 0 To _ParamCount
                ret(i) = New Argument(_InputMappings(i).Parameter, Nothing)
            Next
            Return ret
        End Function
        Friend Function GetArgs(ByVal args() As Object) As Argument()
            Dim ret(_ParamCount) As Argument
            For i As Integer = 0 To _ParamCount
                ret(i) = New Argument(_InputMappings(i).Parameter, args(i))
            Next
            Return ret
        End Function
    End Class

End Namespace